package com.tasks;

import java.util.*;

import com.dao.*;
import com.model.*;
import com.service.Util;
import com.service.impl.CalculateStrService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


@Component
public class CompareStrTasks {
    @Value("${spring.profiles.active}")
    public String env;

    @Autowired
    ReportStrDao reportStrDao;
    @Autowired
    SampleBundDao sampleBundDao;
    @Autowired
    MemberDao memberDao;
    @Autowired
    ReportPublicStrDao reportPublicStrDao;
    @Autowired
    SearchlibResDao searchlibResDao;
    @Autowired
    CalculateStrService calculateStrService;

    protected static int innerlibStart = 0;
    protected static int outlibStart = 0;
    protected static int limit = 1000;

    protected ReportStr selfReportStr;

    private static final Logger log = LoggerFactory.getLogger(CompareStrTasks.class);


//    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
//    @Scheduled(fixedRate = 86400000)
    @Scheduled(cron = "0 0 1 * * ?")
    public void compareStr() {
        //在正式环境运行时，每次运行脚本前，先把老的比对记录清空
        if (env.equals("pro")) {
            clearSearlibResAndUpdateReportStrSetHasCompareFalse();
        }
        int countReportStr = reportStrDao.countReportStr();
        int countReportPublicStr = reportPublicStrDao.countReportPublicStr();
        selfReportStr = reportStrDao.selectFirstReportStrNoCompare();
        //到结果库中查询当前被比对的内库位点是否有没有完成的比对结果，如果有先删除这些结果再进行比对
        if (selfReportStr != null) {
            SearchlibRes unfinishedRes = searchlibResDao.selectOneSearchlibResBySourceStrId(selfReportStr.getId());
            if (unfinishedRes != null) {
                searchlibResDao.deleteSearchlibResBySourceStrId(selfReportStr.getId());
            }
        }

        while (selfReportStr != null) {
            SampleBund sampleBund = sampleBundDao.selectFirstSampleBundBySampleSn(selfReportStr.getSampleSn());
            Member member = null;
            if (sampleBund != null) {
                member = memberDao.selectMemberById(sampleBund.getMemberId());
            }
            int innerLibCompareEnd = innerlibStart + limit;
            int outLibCompareEnd = outlibStart + limit;
            List<ReportStr> innerReportStrList = reportStrDao.selectReportStrLimitExcludeSelf(innerlibStart, limit, selfReportStr.getId());
            List<ReportPublicStr> outReportStrList = reportPublicStrDao.selectReportPublicStrLimit(outlibStart, limit);
            Map<String, String> selfStrMap = getInnerStrLib(selfReportStr);

            List<SearchlibRes> searchResList = new ArrayList<>();
            if (innerReportStrList.size() > 0) {
                for (ReportStr innerReportStr1 : innerReportStrList) {
                    Map<String, String> innerStrMap = getInnerStrLib(innerReportStr1);
                    if (innerStrMap.size() > 0 && selfStrMap.size() > 0) {
                        //按照距离计算的结果
                        Double distance = getDistance(selfStrMap, innerStrMap);
                        Double year = getYear(selfStrMap, innerStrMap);
                        SearchlibRes searchlibRes = new SearchlibRes();
                        searchlibRes.setMemberId(member != null ? member.getId() : 0);
                        searchlibRes.setSourceStrId(selfReportStr.getId());
                        searchlibRes.setTargetStrId(innerReportStr1.getId());
                        searchlibRes.setDistance(distance);
                        searchlibRes.setTargetLib("inner");
                        searchlibRes.setStrNum(selfStrMap.size());
                        searchlibRes.setDistanceVal(distance/selfStrMap.size());
                        searchlibRes.setStrHash("");
                        searchlibRes.setYear(year);
                        searchResList.add(searchlibRes);
                    }

                }
            }

            if (outReportStrList.size() > 0) {
                for (ReportPublicStr reportPublicStr : outReportStrList) {
                    Map<String, String> outStrMap = getOutStrLib(reportPublicStr);
                    if (outStrMap.size() > 0 && selfStrMap.size() >0) {
                        //按照距离计算的结果
                        Double distance = getDistance(selfStrMap, outStrMap);
                        Double year = getYear(selfStrMap, outStrMap);
                        int strNum = getIntersectionNum(selfStrMap,outStrMap);
                        SearchlibRes searchlibResDistance = new SearchlibRes();
                        searchlibResDistance.setMemberId(member != null ? member.getId() : 0);
                        searchlibResDistance.setSourceStrId(selfReportStr.getId());
                        searchlibResDistance.setTargetStrId(reportPublicStr.getId());
                        searchlibResDistance.setDistance(distance);
                        searchlibResDistance.setTargetLib("out");
                        searchlibResDistance.setStrNum(strNum);
                        searchlibResDistance.setDistanceVal(distance/strNum);
                        searchlibResDistance.setStrHash("");
                        searchlibResDistance.setYear(year);
                        searchResList.add(searchlibResDistance);
                    }
                }
            }

            if (searchResList.size() > 0) {
                int insertRes = searchlibResDao.bathInsertSearchlibRes(searchResList);
                if (insertRes > 0) {
                    log.info("成功插入" + searchResList.size() + "条比对结果");
                }

                searchResList.clear();
            }
            innerlibStart = innerLibCompareEnd;
            outlibStart = outLibCompareEnd;
            if (innerlibStart >= countReportStr && outlibStart >= countReportPublicStr) {
                log.info("当前位点" + selfReportStr.getId() +"比对完成");
                reportStrDao.updateReportStrHasCompareSetTrueByPk(selfReportStr.getId());
                selfReportStr = reportStrDao.selectFirstReportStrNoCompare();
                innerlibStart = 0;
                outlibStart = 0;

            }
        }
    }
    private void clearSearlibResAndUpdateReportStrSetHasCompareFalse() {
        searchlibResDao.truncateSearchlibRes();
        reportStrDao.updateReportStrSetHasCompareFalse();
    }
    private Double getDistance(Map<String, String> selfStrMap, Map<String, String> innerStrMap) {
        return calculateStrService.getDistance(selfStrMap,innerStrMap);
    }

    private Double getYear(Map<String, String> selfStrMap, Map<String, String> innerStrMap) {
        return calculateStrService.getYear(selfStrMap,innerStrMap);
    }

    private Integer getIntersectionNum(Map<String,String>selfStrMap,Map<String,String>outStrMap) {
        return calculateStrService.getIntersectionNum(selfStrMap,outStrMap);
    }
    private Map<String, String> getOutStrLib(ReportPublicStr reportPublicStr) {
        return calculateStrService.getPublicStrLib(reportPublicStr);
    }

    private Map<String, String> getInnerStrLib(ReportStr reportStr) {
        return calculateStrService.getReportStrMap(reportStr);
    }

    private Map<String, Double> getYearU() {
        return calculateStrService.getYearU();
    }

    //判断浮点数（double和float）
    private boolean isDouble(String str) {
        return Util.isDouble(str);
    }
}